home *** CD-ROM | disk | FTP | other *** search
/ Mesolore / Mesolore - Disc 1.iso / mac / data / Nuttall Search.dir / 00003_Script_Dropdown List < prev    next >
Text File  |  2001-03-05  |  35KB  |  1,036 lines

  1. --Add the folowing fix:
  2.  
  3. --The "Dropdown List" behavior has provoked a couple of bug reports.
  4. --Bart Pietercil pointed out that you can't place two Dropdown Lists one
  5. --above the other: if you do, one of them will appear (closed) above the
  6. --other.  You can fix this by adding a line at the beginning of the
  7. --OpenList and CloseList handlers:
  8. --
  9. --  on OpenList me -- sent by mouseDown
  10. --    mySprite.locZ = the maxInteger
  11. --    -- more stuff
  12. --  end OpenList
  13. --
  14. --  on CloseList me -- sent by mouseUpOutside, HiliteSelection, CheckClick
  15. --    mySprite.locZ = spriteNum
  16. --    -- more stuff
  17. --  end CloseList
  18.  
  19. -- DESCRIPTION --
  20.  
  21. on getBehaviorDescription me
  22.   return "¼
  23. DROPDOWN LIST"&RETURN&RETURN&"¼
  24. Drop this behavior on a Field member to create a pop-up list.  ¼
  25. Animations continue while the the list is kept open."&RETURN&RETURN&"¼
  26. When the user clicks on the sprite, the dropdown list opens to reveal all ¼
  27. its items.  if the user immediately releases the mouse, the menu remains ¼
  28. open until the next click.  When the user selects a menu item, the menu ¼
  29. closes up to displays the selected item.  If the user clicks elsewhere, ¼
  30. the menu closes to display the previously selected item."&RETURN&RETURN&"¼
  31. You can use one of two modes for the Dropdown list:"&RETURN&"¼
  32. 1) To allow the user to make a selection"&RETURN&"¼
  33. 2) To execute a simple command."&RETURN&RETURN&"¼
  34. SELECTION"&RETURN&"¼
  35. In the first case, you will need to determine what the user selected.  ¼
  36. To interrogate the Dropdown list, use syntax similar to the following:"&¼
  37. RETURN&RETURN&"¼
  38.    put sendAllSprites (#DropList_Selection, 'listName')"&RETURN&RETURN&"¼
  39. This returns a property list with all the necessary information:"&¼
  40. RETURN&RETURN&"¼
  41. -- [#item: 1, #text: 'First choice', #type: #content, #sprite: 1]"&¼
  42. RETURN&RETURN&"¼
  43. See the 'Notes for developers' in the script itself for more details."&¼
  44. RETURN&RETURN&"¼
  45. You can choose any character to act as a checkmark to indicate the previous ¼
  46. selection when the dropdown list is open.  Depending on the font you use, you ¼
  47. may wish to use a checkmark followed by a space.  Reopen the Behavior ¼
  48. Parameters dialog to make such a change."&RETURN&RETURN&"¼
  49. EXECUTION"&RETURN&"¼
  50. You can choose to execute three types of command:"&RETURN&"¼
  51. a) go marker (<selected item>)"&RETURN&"¼
  52. b) go movie '<selected item>'"&RETURN&"¼
  53. c) do '<selected item>'"&RETURN&RETURN&"¼
  54. The type of command depends on the contents of the list.  The behavior can ¼
  55. automatically create a list of markers in the current movie, or movies in the ¼
  56. current folder... or it can leave the contents of the Field as they are.  In ¼
  57. this last case, choosing 'Execute' makes the behavior treat the selected item ¼
  58. as a Lingo command.  You should include handlers in a movie script to deal ¼
  59. with such commands."&RETURN&RETURN&"¼
  60. TIP: Place the dropdown list sprite in a high channel where it will not be covered ¼
  61. by any other sprites."&RETURN&RETURN&"¼
  62. PERMITTED MEMBER TYPES:"&RETURN&"Field members"&RETURN&RETURN&"¼
  63. PARAMETERS:"&RETURN&"¼
  64. * Name of the list (used in sendAllSprite calls)"&RETURN&"¼
  65. * Purpose - Choose between:"&RETURN&"¼
  66.   - Marker: creates a list of markers in current movie"&RETURN&"¼
  67.   - Movie: creates a list of movies with the same pathName"&RETURN&"¼
  68.   - Field contents: uses the current contents of the field"&RETURN&"¼
  69. * Action on selection - Choose between:"&RETURN&"¼
  70.   - Execute: go movie | go marker | do selectedLine"&RETURN&"¼
  71.   - Select:  return the selected item if called to do so"&RETURN&"¼
  72. * Checkmark to indicate currently selected item"&RETURN&"¼
  73. * Standard style: deselect this option if you want to give the Field member a ¼
  74. particular border, margin or shadow."&RETURN&RETURN&"¼
  75. PUBLIC METHODS:"&RETURN&"¼
  76. => Get info on currently selected item"&RETURN&"¼
  77. => Set the contents of the dropdown list"&RETURN&"¼
  78. => Toggle between Execute and Select modes"&RETURN&"¼
  79. => Get behavior reference"
  80. end getBehaviorDescription
  81.  
  82.  
  83. on getBehaviorTooltip me
  84.   return "¼
  85. Use with Field members only."&RETURN&RETURN&"¼
  86. Turn a Field into a pop-up list to execute commands"&RETURN&"¼
  87. or store selected data.  See the Behavior Description"&RETURN&"¼
  88. for tips on executing items with the 'do' command or"&RETURN&"¼
  89. accessing the currently selected item using Lingo."&RETURN&RETURN&"¼
  90. Options: create a list of movies with the same path"&RETURN&"¼
  91. name, or a list of markers in the current movie."
  92. end getBehaviorTooltip
  93.  
  94.  
  95.  
  96. -- NOTES FOR DEVELOPERS --
  97. --
  98. -- The handlers of this behavior fall into three types: those that determine
  99. -- the contents of the list, those that react to the user's mouse clicks, and
  100. -- those that allow Lingo access to the current selection.
  101. --
  102. -- CREATING THE CONTENTS
  103. -- The author has a choice of three types of content: #movie, #marker or
  104. -- the current contents of the field.  The latter two are easy to deal with
  105. -- since the information already exists in the form of string.  (The labelList
  106. -- is in fact a string, not a list).
  107. --
  108. -- Creating a RETURN delimited string of movies is more complex.  We want to
  109. -- list all movies in the same folder as the current movie, or which are in
  110. -- subfolders of this folder.  The CreateMovieLists handler uses recursion.
  111. -- The getNthFileNameInFolder function is used to look at each item in the
  112. -- folder in turn.  If it is a movie, it is added to the list.  If not, it is
  113. -- treated as if it were itself a folder.  The MovieList handler calls a clone
  114. -- of itself to examine the contents of this new folder.  Any new movies found
  115. -- are added to the growing movies variable.
  116.  
  117. -- Once the content has been established, the dimensions of the list can
  118. -- be calculated.  Setting the rect of a text member changes the size of the
  119. -- onstage sprite.  It does not in fact change the rect of the member.  This
  120. -- will always return the full height of the text.  This behavior exploits this
  121. -- fact to create the myOpenRect property.  A RETURN character is then added to
  122. -- the end of the list, to ensure that the hilite of the last line of the list
  123. -- runs the full width of the field.
  124.  
  125. -- ALLOWING FOR CHECKMARKS
  126. -- Actually, a RETURN delimited string is not quite enough.  I place 3 spaces
  127. -- at the beginning of each line, to make room for a checkmark.  if the menu is
  128. -- set to "select" (rather than ("execute"), then it needs to display a
  129. -- checkmark to remind the user which item was selected previously.  Most
  130. -- characters that would be used as a checkmark, in most fonts, will be about
  131. -- two spaces wide.  So I place the checkmark in spaces one and two.  If you
  132. -- use a proportional font, this will make the item jump one space to the left.
  133. -- To solve this use a character followed by a space as your checkmark: "* ".
  134. --
  135. -- Rather than add and subtract spaces constantly, I chose to create a list
  136. -- with number items, containing the original text: myItemsList.  This has the
  137. -- additional advantage of storing the frame numbers for each marker, if 
  138. -- you choose to create a list of markers.  I am indebted to Pim van Bochoven
  139. -- for showing me how to create a list which includes duplicate marker names.
  140.  
  141. -- INTERACTING WITH THE USER
  142. -- The major difficulty here is to determine the size and position of the open
  143. -- list.  Ideally, the list should open so that the current selection is under
  144. -- the cursor.  If the list is too near the top or bottom of the Stage for this
  145. -- to happen, its position is shifted up or down the appropriate number of 
  146. -- lines.
  147. --
  148. -- This is not the standard behavior of a pop-up menu.  Standard menu behavior
  149. -- would require either an Xtra or more than one sprite.
  150. --
  151. -- The difference between this list behavior and a pop-up menu becomes even
  152. -- clearer if the list is too long to fit on the Stage.  If this happens, a
  153. -- scrollbar is provided.
  154. --
  155. -- A mouseUp can have two meanings: a fast click will hold the list open, a
  156. -- longer click indicates that the user has made a selection.  the value of
  157. -- the ticks when the mouse is first pressed is saved in myClickTicks.  This
  158. -- value is compared against the ticks as soon as the mouse is released.  If
  159. -- the difference is less than 30 ticks (half a second) the list wil remain
  160. -- open.  Otherwise, the behavior considers that a selection has been made.
  161. --
  162. -- If the list remains open, a click elsewhere should close it.  The
  163. -- prepareFrame handler checks if the clickOn is the number of the list
  164. -- sprite.  If not, the clicks was elsewhere.
  165. --
  166. -- When the list closes, two things must happen: the rect of the member has
  167. -- to be set to the height of a single line, and the contents of the field must
  168. -- be scrolled so that the selected item appears in the remaining space.  The 
  169. -- scrollTop property gives the height in pixels between the start of the text
  170. -- and the top of the visible line of text.
  171.  
  172. -- Note the simplicity of the ScrollTo handler.
  173.  
  174. -- ACCESSING THE CURRENT SELECTION
  175. -- The DropList_Selection handler gives flexible access to the current
  176. -- selection.  If only one dropdown list appears in the current frame, use..
  177. --
  178. --   put sendAllSprites (#DropList_Selection)
  179. --
  180. -- ...to print out a list in the Message Window.  If more than one list is
  181. -- present, then you can either include the list's name in your call:
  182. --
  183. --   put sendAllSprites (#DropList_Selection, "Markers")
  184. --   -- [#item: 1, #text: "Intro, #type: #marker, #sprite: 1]
  185. --
  186. -- ... or send in an empty property list for each dropdown list to fill in with
  187. -- its own details:
  188. --
  189. --   put sendAllSprites (#DropList_Selection, [:])
  190. --   -- ["Markers": [#item: 1, #text: "Intro", #type: #marker, #sprite: 1],
  191. --   "Movies": [#item: 5, #text: "Main", #type: #movie, #sprite: 2]]
  192. --
  193. -- You could also target the list's sprite directly, with a sendSprite call.
  194. -- Any of these calls will return a list specifying:
  195. -- * the number of the selected item
  196. -- * the text of the selected item
  197. -- * the type of data concerned (#movie | #marker | #content)
  198. -- * the dropdown list's spriteNum
  199. --
  200. -- If you collect data for all dropdown lists in a property list, then the name
  201. -- of each dropdown list will also be returned (as the property for each entry).
  202.  
  203. -- EXECUTING CUSTOM LINGO
  204. -- In the Behavior Parameters dialog you can set the list to use the 
  205. -- "Current contents of the field" and to "Execute... do selectedLine".  The
  206. -- behavior will now treat each item in the dropdown list as a Lingo command.
  207. -- You will need to provide handlers in a movie script to treat these commands.
  208. --
  209. -- For example, your dropdown list could contain the following items:
  210. --
  211. --    Register
  212. --    Help
  213. --    Quit
  214. --
  215. -- Only "Quit" is a Lingo keyword that could be executed directly.  For the
  216. -- other two items you would need a movie script with the following handlers:
  217. --
  218. --   on Register
  219. --     go marker ("Register")
  220. --   end
  221. --
  222. --   on Help
  223. --     open window "Help"
  224. --   end
  225.  
  226. -- ALTERING THE CONTENTS OF THE DROPDOWN LIST
  227. -- You can use a #DropList_SetContents call to change the contents of the
  228. -- dropdown list on the fly.  
  229.  
  230. -- If you send either a RETURN delimited string or a list as a parameter, the
  231. -- dropdown list will now behave as if you had chosen  "Current contents of the
  232. -- field" in the Behavior Parameters dialog.  The default item will be the
  233. -- first item in your list.  Example:
  234. --
  235. --  sendSprite (1, #DropList_SetContents, ["Register","Help", "Quit"])
  236. -- 
  237. -- If the dropdown list is set to "Execute... do selectedLine", then make sure
  238. -- that there are handlers in a movie script to deal with each command.
  239. --
  240. -- You can also use the symbols #marker and #movie as a parameter.  This will 
  241. -- automatically create a list of either markers in the current movie, or 
  242. -- movies in the current folder and subfolders.  Examples:
  243. --
  244. --   sendSprite (1, #DropList_SetContents, #marker)
  245. --   sendAllSprites (#DropList_SetContents, #movie, "List 1")
  246.  
  247. -- CHOOSING TO SELECT OR TO EXECUTE AN ITEM
  248. -- You can toggle between the selection and execution modes using a
  249. -- #DropList_ToggleExecution call.  This takes one or two parameters: the new
  250. -- mode and/or the name of the list to toggle.  If you use both parameters, the
  251. -- new mode should appear first.  Example:
  252. --
  253. --    sendAllSprites (#DropList_ToggleExecution, #execute, "Movies")
  254. --
  255. -- If you do not specify a mode, the mode will switch between #execute and
  256. -- #select.  If you do not specify a list, then all dropdown lists in the 
  257. -- current frame will be affected.
  258.  
  259.  
  260.  
  261.  
  262. -- HISTORY --
  263.  
  264. -- 12 - 13 September 1998: written for the D7 Behaviors Palette by James Newton
  265. -- 28- 30 October 1998:  rewritten with help and guidance from Pim van Bochoven
  266. -- to include a selection checkmark and to allow the use of markers with
  267. -- duplicate names.
  268. -- 13 November 1998: additional Public Method handlers added and commented.
  269.  
  270.  
  271. -- PROPERTIES --
  272.  
  273. property spriteNum
  274. property mySprite
  275. -- author-defined parameters
  276. property myName
  277. property myContent
  278. property myAction
  279. property myCheckmark
  280. property myStandard
  281. -- internal properties
  282. property myListMember
  283. property myField
  284. property myItemsList
  285. property myRestoreString
  286. property myDisplayString
  287. -- dimensions
  288. property myItemHeight
  289. property myOpenRect
  290. property myClosedRect
  291. property myClosedLoc
  292. property myOpenHeight
  293. property myStageHeight
  294. property myStageWidth
  295. -- selection
  296. property mySelectedItem
  297. property myListIsOpen
  298. property myClickTicks
  299. property myLastHilite
  300.  
  301.  
  302.  
  303. -- EVENT HANDLERS --
  304.  
  305. on beginSprite me
  306.   Initialize me
  307. end beginSprite
  308.  
  309.  
  310. on mouseDown me
  311.   if not myListIsOpen then OpenList me
  312. end mouseDown
  313.  
  314.  
  315. on prepareFrame me
  316.   CheckListState me
  317. end prepareFrame
  318.  
  319.  
  320. on mouseUp me
  321.   CheckClick me
  322. end mouseUp
  323.  
  324.  
  325. on mouseUpOutside me
  326.   CloseList me
  327. end mouseUpOutside
  328.  
  329.  
  330.  
  331. -- CUSTOM HANDLERS: UTILIZATION --
  332.  
  333. on CheckListState me
  334.   if myListIsOpen then
  335.     if the clickOn <> spriteNum then 
  336.       -- Click outside list while it is held open
  337.       CloseList me
  338.     else
  339.       HiliteSelection me
  340.     end if
  341.   else
  342.     if myContent = #marker and myAction then
  343.       markerNumber      = GetCurrentMarker (me)
  344.       if mySelectedItem = markerNumber then exit
  345.       
  346.       mySelectedItem    = markerNumber
  347.       ScrollTo me, mySelectedItem
  348.     end if
  349.   end if
  350. end CheckListState
  351.  
  352.  
  353. on OpenList me -- sent by mouseDown
  354.   myClickTicks = the ticks
  355.   myListIsOpen = TRUE
  356.   myDisplayString = myRestoreString
  357.   if not myAction then
  358.     put myCheckMark into myDisplayString.line[mySelectedItem].char [1..2]
  359.   end if
  360.   myListMember.text = myDisplayString
  361.   
  362.   currentScroll = myListMember.scrollTop
  363.   
  364.   if myOpenHeight <= myStageHeight then
  365.     -- Show whole list to best advantage
  366.     overShoot = currentScroll - myClosedLoc[2]
  367.     if overShoot < 0 then
  368.       overShoot = myOpenHeight - overShoot - myStageHeight
  369.       if overShoot < 0 then
  370.         -- Simplest case
  371.         mySprite.locV = myClosedLoc[2] - currentScroll
  372.         
  373.       else       
  374.         -- List too low: shift it up so it will appear in full
  375.         lineAdjust = ((overShoot - 1) / myItemHeight) + 1
  376.         pixelAdjust = (lineAdjust * myItemHeight) - overShoot
  377.         openTop = myStageHeight  - myOpenHeight - pixeladjust
  378.         mySprite.locV = openTop
  379.       end if
  380.       
  381.     else     
  382.       -- List too high: shift it down so it will appear in full
  383.       lineAdjust = ((overShoot - 1) / myItemHeight) + 1
  384.       pixelAdjust = lineAdjust * myItemHeight
  385.       openTop = pixelAdjust - overShoot
  386.       mySprite.locV = openTop
  387.     end if
  388.     myListMember.scrollTop = 0
  389.     myListMember.rect = myOpenRect
  390.     
  391.   else   
  392.     -- List is too long to show in full:  show as much as possible...
  393.     mySprite.locV = -2
  394.     clippedRect = myOpenRect.duplicate()
  395.     clippedRect[4] = myStageHeight
  396.     myListMember.rect = clippedRect
  397.     --...and let it a scroll
  398.     myListMember.boxType = #scroll
  399.     if mySprite.right > myStageWidth then
  400.       spriteWIdth = mySprite.right - mySprite.left
  401.       mySprite.locH = myStageWidth - spriteWIdth
  402.     end if
  403.     scrollAdjust = myClosedLoc[2] - mySprite.locV
  404.     myListMember.scrolltop = currentScroll - scrollAdjust
  405.   end if
  406.   
  407.   updateStage
  408. end OpenList
  409.  
  410.  
  411. on HiliteSelection me  -- sent by prepareFrame  
  412.   if the mouseMember <> myListMember then
  413.     if myLastHilite then
  414.       -- Clear hilite to indicate that no action will be taken
  415.       myLastHilite = 0
  416.       hilite char the maxInteger of field myField
  417.     end if
  418.     exit
  419.     
  420.   else
  421.     if myListMember.boxtype = #scroll then AutoScroll me
  422.     -- Hilite the line under the mouse
  423.     listLocV = mouseV() - mySprite.locV + myListMember.scrollTop
  424.     mouseItem = (listLocV / myItemHeight) + 1
  425.   end if
  426.   
  427.   if mouseItem = myLastHilite then exit
  428.   if mouseItem > myItemsList.count then
  429.     myLastHilite = 0
  430.     hilite char the maxInteger of field myField
  431.     exit
  432.   end if
  433.   
  434.   myLastHilite = mouseItem
  435.   if mouseItem = 1 then
  436.     firstCharToHilite = 1
  437.   else
  438.     textBeforeMouseItem = line 1 to (mouseItem - 1) of myDisplayString
  439.     firstCharToHilite = the number of chars of textBeforeMouseItem + 2
  440.     -- Two extra characters = invisible RETURN + first char of mouseItem
  441.   end if
  442.   mouseItemLength = the number of chars of line mouseItem of myDisplayString
  443.   lastCharToHilite = firstCharToHilite + mouseItemLength
  444.   hilite char firstCharToHilite to lastCharToHilite of field myField
  445. end HiliteSelection
  446.  
  447.  
  448. on AutoScroll me -- sent by HiliteSelection
  449.   scrollDownHeight = myItemHeight / 2
  450.   scrollUpHeight = myStageHeight - myItemHeight / 2
  451.   currentScroll = myListMember.scrollTop
  452.   if mouseV() < scrollDownHeight then
  453.     if currentScroll <> 0 then
  454.       newScroll = currentScroll - scrollDownHeight
  455.       myListMember.scrollTop = max (0, newScroll)
  456.     end if
  457.   else if mouseV() > scrollUpHeight then
  458.     maxScroll = myOpenHeight - myStageHeight
  459.     if currentScroll <> maxScroll then
  460.       newScroll = currentScroll + scrollDownHeight
  461.       myListMember.scrollTop = min (maxScroll, newScroll)
  462.     end if
  463.     
  464.   end if
  465. end AutoScroll
  466.  
  467.  
  468. on CheckClick me -- sent by mouseUp
  469.   if the ticks - myClickTicks < 30 then
  470.     -- Fast click: hold list open and get ready to react to the next click 
  471.     myClickTicks = 0 
  472.   else
  473.     if myLasthilite then
  474.       -- Treat selection and close
  475.       mySelectedItem = myLastHilite
  476.     end if
  477.     CloseList me
  478.     if myAction and myLastHilite then
  479.       Execute me
  480.     end if
  481.   end if
  482.   myLastHilite = 0
  483. end CheckClick
  484.  
  485.  
  486. on ScrollTo me, theLine -- sent by Initialize, CloseList
  487.   myListMember.scrollTop = -10
  488.   -- D7 won't set the scrollTop if it thinks it hasn't changed
  489.   myListMember.scrollTop = myItemHeight * (theLine - 1)
  490. end ScrollTo
  491.  
  492.  
  493. on CloseList me -- sent by mouseUpOutside, HiliteSelection, CheckClick
  494.   hilite char the maxInteger of field myField
  495.   if not myAction then
  496.     myListMember.text = myRestoreString
  497.   end if
  498.   mySprite.loc = myClosedLoc
  499.   myListMember.boxType = #fixed
  500.   myListMember.rect = myClosedRect
  501.   ScrollTo (me, mySelectedItem)
  502.   myListIsOpen = FALSE
  503.   if myContent <> #marker then updateStage
  504. end CloseList
  505.  
  506.  
  507. on Execute me -- sent by CheckClick
  508.   theItem = myItemsList[mySelectedItem]
  509.   case myContent of
  510.     #movie:
  511.       if not (the movieName starts (theItem&".")) then
  512.         go movie theItem
  513.       end if
  514.     #marker:  go myItemsList.getPropAt(mySelectedItem)
  515.     #content: load theItem, the clickon ---skb changed
  516.   end case
  517. end Execute
  518.  
  519.  
  520.  
  521. -- CUSTOM HANDLERS: INITIALIZATION --
  522.  
  523. on Initialize me -- sent by beginSprite
  524.   mySprite = sprite(me.spriteNum)
  525.   myListMember = mySprite.member
  526.   
  527.   -- Error checking
  528.   memberType = myListMember.type
  529.   if memberType <> #field then
  530.     ErrorAlert (me, #invalidMemberType, memberType)
  531.   end if
  532.   -- End of error checking
  533.   
  534.   myField = myListMember.number
  535.   -- Convert to symbols
  536.   case myContent of
  537.     "Current contents of the field":  myContent = #content
  538.     "Markers in this movie":          myContent = #marker
  539.     "Movies with the same path name": myContent = #movie
  540.   end case
  541.   
  542.   -- Convert to boolean
  543.   case myAction of
  544.     "Select:  return the selected item when called":
  545.       myAction = FALSE
  546.     "Execute: go movie | go marker | do selectedLine":
  547.       myAction = TRUE
  548.   end case
  549.   
  550.   -- Ensure that the field properties are properly set
  551.   myListMember.wordWrap  = FALSE
  552.   myListMember.alignment = "left"
  553.   myListMember.boxType = #fixed
  554.   if myStandard then
  555.     myListMember.border = 1
  556.     myListMember.margin = 2
  557.     myListMember.boxDropShadow = 2
  558.   end if
  559.   
  560.   -- Determine the field's content
  561.   CreateItems me
  562.   mySelectedItem = DefaultItem (me)
  563.   SetDimensions me
  564.   
  565.   -- Display closed list
  566.   myListMember.rect = myClosedRect
  567.   ScrollTo (me, mySelectedItem)
  568. end Initialize
  569.  
  570.  
  571.  
  572. on CreateItems me -- sent by Initialize
  573.   case myContent of
  574.     #content:
  575.       CreateContentsLists (me)
  576.     #marker:
  577.       myRestoreString = AddSpaces (me, the labelList)
  578.       myItemsList     = GetMarkedFrames (me)
  579.     #movie:
  580.       myRestoreString = ""
  581.       myItemsList     = [:]
  582.       saveDelimiter = the itemDelimiter
  583.       the itemDelimiter = "."
  584.       CreateMovieLists (me, the moviePath)
  585.       set the itemDelimiter = saveDelimiter
  586.   end case
  587. end CreateItems
  588.  
  589.  
  590. on AddSpaces me, theText
  591.   -- Adds three spaces to the beginning of every line
  592.   repeat while the last char of theText = RETURN
  593.     delete the last char of theText
  594.   end repeat
  595.   
  596.   newString = EMPTY
  597.   lineCount = theText.line.count
  598.   repeat while lineCount
  599.     theItem = theText.line[lineCount]
  600.     put "   "&theItem&RETURN before newString
  601.     lineCount = lineCount - 1
  602.   end repeat
  603.   return newString
  604. end AddSpaces
  605.  
  606.  
  607. on CreateContentsLists me
  608.   theText = myListMember.text
  609.   repeat while the last char of theText = RETURN
  610.     delete the last char of theText
  611.   end repeat
  612.   
  613.   myRestoreString = EMPTY
  614.   myItemsList     = [:]
  615.   lineCount       = theText.line.count
  616.   repeat with i = 1 to lineCount
  617.     theItem = theText.line[i]
  618.     -- Strip myCheckmark and any spaces
  619.     if SPACE&myCheckmark contains theItem.char[1] then
  620.       delete theItem.char[1]
  621.       repeat while theItem.char[1] = " "
  622.         delete theItem.char[1]
  623.       end repeat
  624.     end if
  625.     -- Ensure that the line starts with 3 spaces
  626.     myRestoreString = myRestoreString&"   "&theItem&RETURN
  627.     myItemsList.addProp(i, theItem)
  628.   end repeat
  629. end CreateContentsLists
  630.  
  631.  
  632. on GetMarkedFrames me
  633.   markerList = [:]
  634.   sort markerList
  635.   
  636.   lastCheckedMarker = 0
  637.   if marker (1) <> marker (-the maxInteger / 2) then
  638.     -- We're after the first marker
  639.     repeat with i = 0 down to -the maxInteger
  640.       checkMarker = marker(i)
  641.       if checkMarker = lastCheckedMarker then exit repeat
  642.       lastCheckedMarker = checkMarker
  643.       markerList.addProp (checkMarker, 0)
  644.     end repeat
  645.   end if
  646.   
  647.   if marker (0) <> marker (the maxInteger / 2) then
  648.     -- We're before the last marker
  649.     repeat with i = 1 to the maxInteger
  650.       checkMarker = marker(i)
  651.       if checkMarker = lastCheckedMarker then exit repeat
  652.       lastCheckedMarker = checkMarker
  653.       markerList.addProp(checkMarker, 0)
  654.     end repeat
  655.   end if 
  656.   
  657.   i = markerList.count()
  658.   theLabels = the labelList
  659.   repeat while i
  660.     markerList [i] = theLabels.line [i]
  661.     i = i - 1
  662.   end repeat
  663.   return markerList
  664. end GetMarkedFrames
  665.  
  666.  
  667. on CreateMovieLists me, folderName -- sent by GetListItems
  668.   -- Recursive handler
  669.   if (the machineType = 256) then
  670.     fileDelimiter = "\"
  671.   else
  672.     fileDelimiter = ":"
  673.   end if
  674.   
  675.   fileCount = 0
  676.   repeat while TRUE
  677.     fileCount = fileCount + 1
  678.     theFileName   = getNthFileNameInFolder (folderName, fileCount)
  679.     if theFileName = EMPTY then
  680.       -- No more files
  681.       return -- movieString
  682.     else
  683.       -- Check if theFile is a movie
  684.       case item 2 of theFileName of
  685.         "dir", "dxr", "dcr":
  686.           theMovie        = item 1 of theFileName
  687.           myRestoreString = myRestoreString&"   "&theMovie&RETURN
  688.           movieCount      = myItemsList.count() + 1
  689.           myItemsList.addProp(movieCount, theMovie)
  690.         otherwise
  691.           -- Check if theFile is not in fact a folder: use recursion
  692.           CreateMovieLists (me, folderName&theFileName&fileDelimiter)
  693.       end case
  694.     end if
  695.   end repeat
  696. end MovieList
  697.  
  698.  
  699. on DefaultItem me -- sent by Initialize
  700.   case myContent of
  701.     #content: return 1
  702.     #marker:  return GetCurrentMarker (me)
  703.     #movie:
  704.       saveDelimiter = the itemDelimiter
  705.       set the itemDelimiter to "."
  706.       shortName = item 1 of the movieName 
  707.       set the itemDelimiter = saveDelimiter
  708.       return myItemsList.getPos (shortName)
  709.   end case
  710. end DefaultItem
  711.  
  712.  
  713. on SetDimensions me
  714.   -- Determine the dimensions of the list
  715.   saveLastChar      = the last char of myRestoreString -- Should be RETURN
  716.   delete the last char of myRestoreString
  717.   myListMember.text = myRestoreString
  718.   myItemHeight      = myListMember.lineHeight
  719.   myOpenRect        = myListMember.rect
  720.   myClosedRect      = myOpenRect.duplicate()
  721.   myClosedRect[4]   = myItemHeight + (myListMember.margin / 2)
  722.   myClosedLoc       = mySprite.loc
  723.   addedHeight       = (myListMember.margin * 2) + myListMember.boxDropShadow
  724.   myOpenHeight      = myOpenRect.bottom + addedHeight
  725.   
  726.   windowRect        = (the activeWindow).rect
  727.   myStageHeight     = windowRect.bottom - windowRect.top
  728.   myStageWidth      = windowRect.right  - windowRect.left
  729.   myRestoreString   = myRestoreString&saveLastChar
  730.   myListMember.text = myRestoreString
  731. end SetDimensions
  732.  
  733.  
  734. on GetCurrentMarker me -- sent by Initialize
  735.   -- Also used to update display if playback head moved by some other means
  736.   markerPosition = myItemsList.findPos(the frame)
  737.   if not markerPosition then
  738.     markerPosition = myItemsList.findPosNear(the frame) - 1
  739.   end if
  740.   return max (1, markerPosition)
  741. end GetCurrentMarker
  742.  
  743.  
  744.  
  745. -- PUBLIC METHOD (response to #sendSprite, #sendAllSprites, #call) --
  746.  
  747. on DropList_Selection me, propListOrString
  748.   -- Returns the current selection of the dropdown list.  If you have several 
  749.   -- dropdown lists with different names, then you can use sendAllSprites call
  750.   -- with a property list as a parameter.  Example:
  751.   --
  752.   --   put sendAllSprites (#DropList_Selection, [:])
  753.   --   -- ["Markers": [#item: 1, #text: "Intro", #type: #marker, #sprite: 1],
  754.   --   "Movies": [#item: 5, #text: "Main", #type: #movie, #sprite: 2]]
  755.   
  756.   -- If you want the current selection of a particular list then use its name:
  757.   --
  758.   --   put sendAllSprites (#DropList_Selection, "Markers")
  759.   --   -- [#item: 1, #text: "Intro", #type: #marker, #sprite: 1]
  760.   --
  761.   -- If you know the sprite number of the list, then you can call it directly:
  762.   --
  763.   --   put sendSprite (2, #DropList_Selection)
  764.   --   -- [#item: 5, #text: "Main", #type: #movie, #sprite: 2]
  765.   
  766.   if stringP (propListOrString) then
  767.     if propListOrString <> myName then exit
  768.   end if
  769.   
  770.   data = ¼
  771.  #item:   mySelectedItem, ¼
  772.  #text:   myItemsList[mySelectedItem], ¼
  773.  #type:   myContent, ¼
  774.  #sprite: spriteNum ¼
  775. ]
  776.   if ilk (propListOrString) <> #propList then
  777.     return data
  778.   else
  779.     propListOrString.addProp(myName, data)
  780.     return propListOrString
  781.   end if
  782. end DropList_Selection
  783.  
  784.  
  785. on DropList_SetContents me, theContents, theListName
  786.   -- Changes the contents of the dropdown list to theContents.  This can be 
  787.   -- either a RETURN delimited string, a list, #marker or #movie.
  788.   -- "theListName" is an optional parameter which allows you to change the
  789.   -- contents of a given list by using its name rather than by calling a
  790.   -- specific sprite number or behavior.  Examples:
  791.   --
  792.   -- sendSprite (1, #DropList_SetContents, #movies)
  793.   --
  794.   -- sendAllSprites (#DropList_SetContents, #marker, "List 1")
  795.   --
  796.   -- objectRef = sendAllSprites (#DropList_GetReference, "Lingo")
  797.   -- call (#DropList_SetContents, objectRef, ["Register","Help", "Quit"])
  798.   
  799.   if not voidP (theListName) then
  800.     if theListName <> myName then exit
  801.   end if
  802.   
  803.   case ilk (theContents) of
  804.     #string:
  805.       myListMember.text = theContents
  806.       myContent = #content
  807.       Initialize me
  808.     #list:
  809.       listItems = ""
  810.       lineCount = theContents.count
  811.       repeat with i = 1 to lineCount
  812.         theLine = string (theContents[i])
  813.         put theLine&RETURN after listItems
  814.       end repeat
  815.       myListMember.text = listItems
  816.       myContent = #content
  817.       Initialize me
  818.     #symbol:
  819.       case theContents of
  820.         #marker:
  821.           myContent = #marker
  822.           Initialize me
  823.         #movie:
  824.           myContent = #movie
  825.           Initialize me
  826.         otherwise
  827.           return #invalidListContents
  828.       end case
  829.     otherwise
  830.       return #invalidListContents
  831.   end case
  832. end DropList_SetContents
  833.  
  834.  
  835. on DropList_ToggleExecution me, executeMode, listName
  836.   -- Determines whether the dropdown list executes any lingo when an item is
  837.   -- selected, or whether it simply retains the selection data.
  838.   --
  839.   -- "listName" is an optional parameter.  You can use it to change the
  840.   -- setting of a given list by using its name rather than by calling a
  841.   -- specific sprite number or behavior.  This example makes the dropdown list
  842.   -- named "Movies" execute when an item is selected:
  843.   --
  844.   --    sendAllSprites (#DropList_ToggleExecution, TRUE, "Movies")
  845.   --
  846.   -- If you use a sendAllSprites message without the listName parameter, all
  847.   -- dropdown lists will be affected.  This example switches all dropdown lists
  848.   -- to #select mode:
  849.   --
  850.   --    sendAllSprites (#DropList_ToggleExecution, #select)
  851.   --
  852.   -- "executeMode" can take any of five values:
  853.   -- * #execute and TRUE will make the dropdown list execute as appropriate
  854.   --    when an item is selected.
  855.   -- * #select and FALSE will make the dropdown list do nothing when an item
  856.   --    is selected.  Use a #DropList_Selection call to get the selection info.
  857.   -- * void (or leaving the parameter blank) will toggle the behavior between
  858.   --    #execute and #select mode.
  859.   -- You can use a list name as the only parameter; this will toggle the 
  860.   -- execute mode of the named list.  This example toggles the execute mode of
  861.   -- a dropdown list named "Lingo":
  862.   -- 
  863.   --    sendAllSprites (#DropList_ToggleExecution, "Lingo")
  864.   --  
  865.   --  This example sets the dropdown list in sprite 1 to select mode:
  866.   --
  867.   --    sendSprite (1, #DropList_ToggleExecution, FALSE)
  868.   
  869.   
  870.   if not voidP (listName) then
  871.     if listName <> myName then
  872.       exit
  873.     end if
  874.   else if stringP (executeMode) then
  875.     -- Treat executeMode as if it were listName and executeMode were void
  876.     if executeMode = myName then
  877.       myAction = not myAction
  878.     else
  879.       exit
  880.     end if
  881.   end if
  882.   
  883.   if voidP (executeMode) then
  884.     myAction = not myAction
  885.   else
  886.     case executeMode of
  887.       #execute, TRUE: myAction = TRUE
  888.       #select, FALSE: myAction = FALSE
  889.       otherwise
  890.         return #invalidExecuteMode
  891.     end case
  892.   end if
  893. end DropList_ToggleExecution
  894.  
  895.  
  896. on DropList_GetReference me, propListOrString
  897.   -- Returns the object reference of this behavior.  If you have several 
  898.   -- dropdown lists with different names, then you can use sendAllSprites call
  899.   -- with a property list as a parameter.  Example:
  900.   --
  901.   --   put sendAllSprites (#DropList_GetReference, [:])
  902.   --   -- ["Markers": <objectRef>, "Movies": <objectRef>, "Lingo": <objectRef>]
  903.   --
  904.   -- If you want the behavior reference of a particular list then use its name:
  905.   --
  906.   --   put sendAllSprites (#DropList_GetReference, "Markers")
  907.   --   -- <offspring "Dropdown List" 2 2ee89e8>
  908.   --
  909.   -- If you know the sprite number of the list, then you can call it directly:
  910.   --
  911.   --   put sendSprite (1, #DropList_GetReference)
  912.   --   -- <offspring "Dropdown List" 2 2ee89e8>
  913.   
  914.   case ilk(propListOrString) of
  915.     #propList:
  916.       propListOrString.addProp(myName, me)
  917.       return propListOrString
  918.     #string:
  919.       if propListOrString = myName then return me
  920.     otherwise
  921.       return me
  922.   end case
  923. end DropList_GetReference
  924.  
  925.  
  926.  
  927. -- ERROR CHECKING --
  928.  
  929. on ErrorAlert me, theError, data
  930.   -- sent by getPropertyDescriptionList, Initialize
  931.   case theError of
  932.     #getPDLError:
  933.       alert "¼
  934. Error: This behavior works only with Field members."&RETURN&RETURN&"¼
  935. Hit OK and then delete this behavior from the sprite."&RETURN&RETURN&"¼
  936. For more information on deleting Behaviors, see the Help system."
  937.       if the optionDown then
  938.         return ¼
  939. [ ¼
  940.  #getPDLError: ¼
  941.  [ ¼
  942.   #comment: "ERROR:   Wrong member type.   Click 'Cancel'."&RETURN&"¼
  943.              Use only with Field members.", ¼
  944.   #format:  #string, ¼
  945.   #range:   [""], ¼
  946.   #default:  "" ¼
  947.  ] ¼
  948. ]
  949.       end if
  950.       
  951.     #invalidMemberType:
  952.       -- Determine the behavior's name
  953.       behaviorName = string (me)
  954.       delete word 1 of behaviorName
  955.       delete the last word of behaviorName
  956.       delete the last word of behaviorName
  957.       
  958.       alert "¼
  959. BEHAVIOR ERROR: Frame "&the frame&", Sprite "&me.spriteNum&RETURN&RETURN&"¼
  960. Behavior "&behaviorName&" only works with Field members."&¼
  961. RETURN&RETURN&"Current member type = #"&data
  962.       halt
  963.   end case
  964. end ErrorAlert
  965.  
  966.  
  967.  
  968. -- AUTHOR-DEFINED PARAMETERS --
  969.  
  970. on getPropertyDescriptionList me
  971.   
  972.   if not the currentSpriteNum then exit
  973.   
  974.   -- Error check: does current sprite contain appropriate member type?
  975.   theMember = sprite(the currentSpriteNum).member
  976.   memberType = theMember.type
  977.   permittedTypes = PermittedMemberTypes(me)
  978.   if not permittedTypes.getPos(memberType) then
  979.     return errorAlert (me, #getPDLError, permittedTypes)
  980.   end if
  981.   
  982.   -- No errors detected: continue as usual ...
  983.   
  984.   return ¼
  985. [ ¼
  986.  #myName: ¼
  987.  [ ¼
  988.   #comment: "Name of this list:", ¼
  989.   #format:  #string, ¼
  990.   #default: "List "&the currentSpriteNum ¼
  991.  ], ¼
  992.  #myContent: ¼
  993.  [ ¼
  994.   #comment: "Contents of list:", ¼
  995.   #format:  #string, ¼
  996.   #range:  ¼
  997.   [¼
  998.    "Current contents of the field", ¼
  999.    "Markers in this movie", ¼
  1000.    "Movies with the same path name" ¼
  1001.   ], ¼
  1002.   #default: "Current contents of the field" ¼
  1003.  ], ¼
  1004.  #myAction: ¼
  1005.  [ ¼
  1006.   #comment: "Purpose of list:", ¼
  1007.   #format:  #string, ¼
  1008.   #range :  ¼
  1009.   [ ¼
  1010.    "Select:  return the selected item when called", ¼
  1011.    "Execute: go movie | go marker | do selectedLine" ¼
  1012.   ], ¼
  1013.   #default: "Select:  return the selected item when called" ¼
  1014.  ], ¼
  1015.  #myCheckmark: ¼
  1016.  [ ¼
  1017.   #comment: "Checkmark to indicate currently selected item:", ¼
  1018.   #format:  #string, ¼
  1019.   #default: ">" ¼
  1020.  ], ¼
  1021.  #myStandard: ¼
  1022.  [ ¼
  1023.   #comment: "Use standard style?", ¼
  1024.   #format:  #boolean, ¼
  1025.   #default:  TRUE ¼
  1026.  ] ¼
  1027. ]
  1028. end getPropertyDescriptionList
  1029.  
  1030.  
  1031. on PermittedMemberTypes me
  1032.   -- sent by getBehaviorDescription, getPropertyDescriptionList,
  1033.   -- Initialize, ErrorAlert
  1034.   return [#field] 
  1035. end PermittedMemberTypes